home *** CD-ROM | disk | FTP | other *** search
/ PCGUIA 2010 Software/Programs / PCGuia_programas.iso / Software / Utils / VLC Media Player / vlc-1.0.3-win32.exe / sdk / include / vlc / plugins / vlc_arrays.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-10-30  |  22.4 KB  |  612 lines

  1. /*****************************************************************************
  2.  * vlc_arrays.h : Arrays and data structures handling
  3.  *****************************************************************************
  4.  * Copyright (C) 1999-2004 the VideoLAN team
  5.  * $Id$
  6.  *
  7.  * Authors: Samuel Hocevar <sam@zoy.org>
  8.  *          Cl├⌐ment Stenac <zorglub@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24.  
  25. #ifndef VLC_ARRAYS_H_
  26. #define VLC_ARRAYS_H_
  27.  
  28. /**
  29.  * \file
  30.  * This file defines functions, structures and macros for handling arrays in vlc
  31.  */
  32.  
  33. /**
  34.  * Simple dynamic array handling. Array is realloced at each insert/removal
  35.  */
  36. #if defined( _MSC_VER ) && _MSC_VER < 1300 && !defined( UNDER_CE )
  37. #   define VLCCVP (void**) /* Work-around for broken compiler */
  38. #else
  39. #   define VLCCVP
  40. #endif
  41. #define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \
  42.     do                                                                        \
  43.     {                                                                         \
  44.         if( !i_oldsize ) (p_ar) = NULL;                                       \
  45.         (p_ar) = VLCCVP realloc( p_ar, ((i_oldsize) + 1) * sizeof(*(p_ar)) ); \
  46.         if( (i_oldsize) - (i_pos) )                                           \
  47.         {                                                                     \
  48.             memmove( (p_ar) + (i_pos) + 1, (p_ar) + (i_pos),                  \
  49.                      ((i_oldsize) - (i_pos)) * sizeof( *(p_ar) ) );           \
  50.         }                                                                     \
  51.         (p_ar)[i_pos] = elem;                                                 \
  52.         (i_oldsize)++;                                                        \
  53.     }                                                                         \
  54.     while( 0 )
  55.  
  56. #define REMOVE_ELEM( p_ar, i_oldsize, i_pos )                                 \
  57.     do                                                                        \
  58.     {                                                                         \
  59.         if( (i_oldsize) - (i_pos) - 1 )                                       \
  60.         {                                                                     \
  61.             memmove( (p_ar) + (i_pos),                                        \
  62.                      (p_ar) + (i_pos) + 1,                                    \
  63.                      ((i_oldsize) - (i_pos) - 1) * sizeof( *(p_ar) ) );       \
  64.         }                                                                     \
  65.         if( i_oldsize > 1 )                                                   \
  66.         {                                                                     \
  67.             (p_ar) = realloc( p_ar, ((i_oldsize) - 1) * sizeof( *(p_ar) ) );  \
  68.         }                                                                     \
  69.         else                                                                  \
  70.         {                                                                     \
  71.             free( p_ar );                                                     \
  72.             (p_ar) = NULL;                                                    \
  73.         }                                                                     \
  74.         (i_oldsize)--;                                                        \
  75.     }                                                                         \
  76.     while( 0 )
  77.  
  78. #define TAB_INIT( count, tab )                  \
  79.   do {                                          \
  80.     (count) = 0;                                \
  81.     (tab) = NULL;                               \
  82.   } while(0)
  83.  
  84. #define TAB_CLEAN( count, tab )                 \
  85.   do {                                          \
  86.     free( tab );                                \
  87.     (count)= 0;                                 \
  88.     (tab)= NULL;                                \
  89.   } while(0)
  90.  
  91. #define TAB_APPEND_CAST( cast, count, tab, p )             \
  92.   do {                                          \
  93.     if( (count) > 0 )                           \
  94.         (tab) = cast realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
  95.     else                                        \
  96.         (tab) = cast malloc( sizeof( void ** ) );    \
  97.     (tab)[count] = (p);                         \
  98.     (count)++;                                  \
  99.   } while(0)
  100.  
  101. #define TAB_APPEND( count, tab, p )             \
  102.     TAB_APPEND_CAST( , count, tab, p )
  103. #define TAB_APPEND_CPP( type, count, tab, p )   \
  104.     TAB_APPEND_CAST( (type**), count, tab, p )
  105.  
  106. #define TAB_FIND( count, tab, p, index )        \
  107.   do {                                          \
  108.         int _i_;                                \
  109.         (index) = -1;                           \
  110.         for( _i_ = 0; _i_ < (count); _i_++ )    \
  111.         {                                       \
  112.             if( (tab)[_i_] == (p) )             \
  113.             {                                   \
  114.                 (index) = _i_;                  \
  115.                 break;                          \
  116.             }                                   \
  117.         }                                       \
  118.   } while(0)
  119.  
  120.  
  121. #define TAB_REMOVE( count, tab, p )             \
  122.   do {                                          \
  123.         int _i_index_;                          \
  124.         TAB_FIND( count, tab, p, _i_index_ );   \
  125.         if( _i_index_ >= 0 )                    \
  126.         {                                       \
  127.             if( (count) > 1 )                   \
  128.             {                                   \
  129.                 memmove( ((void**)(tab) + _i_index_),    \
  130.                          ((void**)(tab) + _i_index_+1),  \
  131.                          ( (count) - _i_index_ - 1 ) * sizeof( void* ) );\
  132.             }                                   \
  133.             (count)--;                          \
  134.             if( (count) == 0 )                  \
  135.             {                                   \
  136.                 free( tab );                    \
  137.                 (tab) = NULL;                   \
  138.             }                                   \
  139.         }                                       \
  140.   } while(0)
  141.  
  142. #define TAB_INSERT_CAST( cast, count, tab, p, index ) do { \
  143.     if( (count) > 0 )                           \
  144.         (tab) = cast realloc( tab, sizeof( void ** ) * ( (count) + 1 ) ); \
  145.     else                                        \
  146.         (tab) = cast malloc( sizeof( void ** ) );       \
  147.     if( (count) - (index) > 0 )                 \
  148.         memmove( (void**)(tab) + (index) + 1,   \
  149.                  (void**)(tab) + (index),       \
  150.                  ((count) - (index)) * sizeof(*(tab)) );\
  151.     (tab)[(index)] = (p);                       \
  152.     (count)++;                                  \
  153. } while(0)
  154.  
  155. #define TAB_INSERT( count, tab, p, index )      \
  156.     TAB_INSERT_CAST( , count, tab, p, index )
  157.  
  158. /**
  159.  * Binary search in a sorted array. The key must be comparable by < and >
  160.  * \param entries array of entries
  161.  * \param count number of entries
  162.  * \param elem key to check within an entry (like .id, or ->i_id)
  163.  * \param zetype type of the key
  164.  * \param key value of the key
  165.  * \param answer index of answer within the array. -1 if not found
  166.  */
  167. #define BSEARCH( entries, count, elem, zetype, key, answer ) \
  168.    do {  \
  169.     int low = 0, high = count - 1;   \
  170.     answer = -1; \
  171.     while( low <= high ) {\
  172.         int mid = (low + high ) / 2; /* Just don't care about 2^30 tables */ \
  173.         zetype mid_val = entries[mid] elem;\
  174.         if( mid_val < key ) \
  175.             low = mid + 1; \
  176.         else if ( mid_val > key ) \
  177.             high = mid -1;  \
  178.         else    \
  179.         {   \
  180.             answer = mid;  break;   \
  181.         }\
  182.     } \
  183.  } while(0)
  184.  
  185.  
  186. /************************************************************************
  187.  * Dynamic arrays with progressive allocation
  188.  ************************************************************************/
  189.  
  190. /* Internal functions */
  191. #define _ARRAY_ALLOC(array, newsize) {                                      \
  192.     (array).i_alloc = newsize;                                              \
  193.     (array).p_elems = VLCCVP realloc( (array).p_elems, (array).i_alloc *    \
  194.                                     sizeof(*(array).p_elems) );             \
  195. }
  196.  
  197. #define _ARRAY_GROW1(array) {                                               \
  198.     if( (array).i_alloc < 10 )                                              \
  199.         _ARRAY_ALLOC(array, 10 )                                            \
  200.     else if( (array).i_alloc == (array).i_size )                            \
  201.         _ARRAY_ALLOC(array, (int)(array.i_alloc * 1.5) )                    \
  202. }
  203.  
  204. #define _ARRAY_GROW(array,additional) {                                     \
  205.      int i_first = (array).i_alloc;                                         \
  206.      while( (array).i_alloc - i_first < additional )                        \
  207.      {                                                                      \
  208.          if( (array).i_alloc < 10 )                                         \
  209.             _ARRAY_ALLOC(array, 10 )                                        \
  210.         else if( (array).i_alloc == (array).i_size )                        \
  211.             _ARRAY_ALLOC(array, (int)((array).i_alloc * 1.5) )              \
  212.         else break;                                                         \
  213.      }                                                                      \
  214. }
  215.  
  216. #define _ARRAY_SHRINK(array) {                                              \
  217.     if( (array).i_size > 10 && (array).i_size < (int)((array).i_alloc / 1.5) ) {  \
  218.         _ARRAY_ALLOC(array, (array).i_size + 5);                            \
  219.     }                                                                       \
  220. }
  221.  
  222. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  223.  
  224. /* API */
  225. #define DECL_ARRAY(type) struct {                                           \
  226.     int i_alloc;                                                            \
  227.     int i_size;                                                             \
  228.     type *p_elems;                                                          \
  229. }
  230.  
  231. #define TYPEDEF_ARRAY(type, name) typedef DECL_ARRAY(type) name;
  232.  
  233. #define ARRAY_INIT(array)                                                   \
  234.   do {                                                                      \
  235.     (array).i_alloc = 0;                                                    \
  236.     (array).i_size = 0;                                                     \
  237.     (array).p_elems = NULL;                                                 \
  238.   } while(0)
  239.  
  240. #define ARRAY_RESET(array)                                                  \
  241.   do {                                                                      \
  242.     (array).i_alloc = 0;                                                    \
  243.     (array).i_size = 0;                                                     \
  244.     free( (array).p_elems ); (array).p_elems = NULL;                        \
  245.   } while(0)
  246.  
  247. #define ARRAY_APPEND(array, elem)                                           \
  248.   do {                                                                      \
  249.     _ARRAY_GROW1(array);                                                    \
  250.     (array).p_elems[(array).i_size] = elem;                                 \
  251.     (array).i_size++;                                                       \
  252.   } while(0)
  253.  
  254. #define ARRAY_INSERT(array,elem,pos)                                        \
  255.   do {                                                                      \
  256.     _ARRAY_GROW1(array);                                                    \
  257.     if( (array).i_size - pos ) {                                            \
  258.         memmove( (array).p_elems + pos + 1, (array).p_elems + pos,          \
  259.                  ((array).i_size-pos) * sizeof(*(array).p_elems) );         \
  260.     }                                                                       \
  261.     (array).p_elems[pos] = elem;                                            \
  262.     (array).i_size++;                                                       \
  263.   } while(0)
  264.  
  265. #define ARRAY_REMOVE(array,pos)                                             \
  266.   do {                                                                      \
  267.     if( (array).i_size - (pos) - 1 )                                        \
  268.     {                                                                       \
  269.         memmove( (array).p_elems + pos, (array).p_elems + pos + 1,          \
  270.                  ( (array).i_size - pos - 1 ) *sizeof(*(array).p_elems) );  \
  271.     }                                                                       \
  272.     (array).i_size--;                                                       \
  273.     _ARRAY_SHRINK(array);                                                   \
  274.   } while(0)
  275.  
  276. #define ARRAY_VAL(array, pos) array.p_elems[pos]
  277.  
  278. #define ARRAY_BSEARCH(array, elem, zetype, key, answer) \
  279.     BSEARCH( (array).p_elems, (array).i_size, elem, zetype, key, answer)
  280.  
  281. #define FOREACH_ARRAY( item, array ) { \
  282.     int fe_idx; \
  283.     for( fe_idx = 0 ; fe_idx < (array).i_size ; fe_idx++ ) \
  284.     { \
  285.         item = (array).p_elems[fe_idx];
  286.  
  287. #define FOREACH_END() } }
  288.  
  289.  
  290. /************************************************************************
  291.  * Dynamic arrays with progressive allocation (Preferred API)
  292.  ************************************************************************/
  293. typedef struct vlc_array_t
  294. {
  295.     int i_count;
  296.     void ** pp_elems;
  297. } vlc_array_t;
  298.  
  299. static inline void vlc_array_init( vlc_array_t * p_array )
  300. {
  301.     memset( p_array, 0, sizeof(vlc_array_t) );
  302. }
  303.  
  304. static inline void vlc_array_clear( vlc_array_t * p_array )
  305. {
  306.     free( p_array->pp_elems );
  307.     memset( p_array, 0, sizeof(vlc_array_t) );
  308. }
  309.  
  310. static inline vlc_array_t * vlc_array_new( void )
  311. {
  312.     vlc_array_t * ret = (vlc_array_t *)malloc( sizeof(vlc_array_t) );
  313.     if( ret ) vlc_array_init( ret );
  314.     return ret;
  315. }
  316.  
  317. static inline void vlc_array_destroy( vlc_array_t * p_array )
  318. {
  319.     if( !p_array )
  320.         return;
  321.     vlc_array_clear( p_array );
  322.     free( p_array );
  323. }
  324.  
  325.  
  326. /* Read */
  327. static inline int
  328. vlc_array_count( vlc_array_t * p_array )
  329. {
  330.     return p_array->i_count;
  331. }
  332.  
  333. static inline void *
  334. vlc_array_item_at_index( vlc_array_t * p_array, int i_index )
  335. {
  336.     return p_array->pp_elems[i_index];
  337. }
  338.  
  339. static inline int
  340. vlc_array_index_of_item( vlc_array_t * p_array, void * item )
  341. {
  342.     int i;
  343.     for( i = 0; i < p_array->i_count; i++)
  344.     {
  345.         if( p_array->pp_elems[i] == item )
  346.             return i;
  347.     }
  348.     return -1;
  349. }
  350.  
  351. /* Write */
  352. static inline void
  353. vlc_array_insert( vlc_array_t * p_array, void * p_elem, int i_index )
  354. {
  355.     TAB_INSERT_CAST( (void **), p_array->i_count, p_array->pp_elems, p_elem, i_index );
  356. }
  357.  
  358. static inline void
  359. vlc_array_append( vlc_array_t * p_array, void * p_elem )
  360. {
  361.     vlc_array_insert( p_array, p_elem, p_array->i_count );
  362. }
  363.  
  364. static inline void
  365. vlc_array_remove( vlc_array_t * p_array, int i_index )
  366. {
  367.     if( i_index >= 0 )
  368.     {
  369.         if( p_array->i_count > 1 )
  370.         {
  371.             memmove( p_array->pp_elems + i_index,
  372.                      p_array->pp_elems + i_index+1,
  373.                      ( p_array->i_count - i_index - 1 ) * sizeof( void* ) );
  374.         }
  375.         p_array->i_count--;
  376.         if( p_array->i_count == 0 )
  377.         {
  378.             free( p_array->pp_elems );
  379.             p_array->pp_elems = NULL;
  380.         }
  381.     }
  382. }
  383.  
  384.  
  385. /************************************************************************
  386.  * Dictionaries
  387.  ************************************************************************/
  388.  
  389. /* This function is not intended to be crypto-secure, we only want it to be
  390.  * fast and not suck too much. This one is pretty fast and did 0 collisions
  391.  * in wenglish's dictionary.
  392.  */
  393. static inline uint64_t DictHash( const char *psz_string, int hashsize )
  394. {
  395.     uint64_t i_hash = 0;
  396.     if( psz_string )
  397.     {
  398.         while( *psz_string )
  399.         {
  400.             i_hash += *psz_string++;
  401.             i_hash += i_hash << 10;
  402.             i_hash ^= i_hash >> 8;
  403.         }
  404.     }
  405.     return i_hash % hashsize;
  406. }
  407.  
  408. typedef struct vlc_dictionary_entry_t
  409. {
  410.     char *   psz_key;
  411.     void *   p_value;
  412.     struct vlc_dictionary_entry_t * p_next;
  413. } vlc_dictionary_entry_t;
  414.  
  415. typedef struct vlc_dictionary_t
  416. {
  417.     int i_size;
  418.     vlc_dictionary_entry_t ** p_entries;
  419. } vlc_dictionary_t;
  420.  
  421. static void * const kVLCDictionaryNotFound = NULL;
  422.  
  423. static inline void vlc_dictionary_init( vlc_dictionary_t * p_dict, int i_size )
  424. {
  425.     p_dict->p_entries = NULL;
  426.  
  427.     if( i_size > 0 )
  428.     {
  429.         p_dict->p_entries = (vlc_dictionary_entry_t **)calloc( i_size, sizeof(*p_dict->p_entries) );
  430.         if( !p_dict->p_entries )
  431.             i_size = 0;
  432.     }
  433.     p_dict->i_size = i_size;
  434. }
  435.  
  436. static inline void vlc_dictionary_clear( vlc_dictionary_t * p_dict,
  437.                                          void ( * pf_free )( void * p_data, void * p_obj ),
  438.                                          void * p_obj )
  439. {
  440.     if( p_dict->p_entries )
  441.     {
  442.         for( int i = 0; i < p_dict->i_size; i++ )
  443.         {
  444.             vlc_dictionary_entry_t * p_current, * p_next;
  445.             p_current = p_dict->p_entries[i];
  446.             while( p_current )
  447.             {
  448.                 p_next = p_current->p_next;
  449.                 if( pf_free != NULL )
  450.                     ( * pf_free )( p_current->p_value, p_obj );
  451.                 free( p_current->psz_key );
  452.                 free( p_current );
  453.                 p_current = p_next;
  454.             }
  455.         }
  456.         free( p_dict->p_entries );
  457.         p_dict->p_entries = NULL;
  458.     }
  459.     p_dict->i_size = 0;
  460. }
  461.  
  462.  
  463.  
  464. static inline void *
  465. vlc_dictionary_value_for_key( const vlc_dictionary_t * p_dict, const char * psz_key )
  466. {
  467.     if( !p_dict->p_entries )
  468.         return kVLCDictionaryNotFound;
  469.  
  470.     int i_pos = DictHash( psz_key, p_dict->i_size );
  471.     vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
  472.  
  473.     if( !p_entry )
  474.         return kVLCDictionaryNotFound;
  475.  
  476.     /* Make sure we return the right item. (Hash collision) */
  477.     do {
  478.         if( !strcmp( psz_key, p_entry->psz_key ) )
  479.             return p_entry->p_value;
  480.         p_entry = p_entry->p_next;
  481.     } while( p_entry );
  482.  
  483.     return kVLCDictionaryNotFound;
  484. }
  485.  
  486. static inline int
  487. vlc_dictionary_keys_count( const vlc_dictionary_t * p_dict )
  488. {
  489.     vlc_dictionary_entry_t * p_entry;
  490.     int i, count = 0;
  491.  
  492.     if( !p_dict->p_entries )
  493.         return 0;
  494.  
  495.     for( i = 0; i < p_dict->i_size; i++ )
  496.     {
  497.         for( p_entry = p_dict->p_entries[i]; p_entry; p_entry = p_entry->p_next ) count++;
  498.     }
  499.     return count;
  500. }
  501.  
  502. static inline char **
  503. vlc_dictionary_all_keys( const vlc_dictionary_t * p_dict )
  504. {
  505.     vlc_dictionary_entry_t * p_entry;
  506.     char ** ppsz_ret;
  507.     int i, count = vlc_dictionary_keys_count( p_dict );
  508.  
  509.     ppsz_ret = (char**)malloc(sizeof(char *) * (count + 1));
  510.  
  511.     count = 0;
  512.     for( i = 0; i < p_dict->i_size; i++ )
  513.     {
  514.         for( p_entry = p_dict->p_entries[i]; p_entry; p_entry = p_entry->p_next )
  515.             ppsz_ret[count++] = strdup( p_entry->psz_key );
  516.     }
  517.     ppsz_ret[count] = NULL;
  518.     return ppsz_ret;
  519. }
  520.  
  521. static inline void
  522. __vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key,
  523.                          void * p_value, bool rebuild )
  524. {
  525.     if( !p_dict->p_entries )
  526.         vlc_dictionary_init( p_dict, 1 );
  527.  
  528.     int i_pos = DictHash( psz_key, p_dict->i_size );
  529.     vlc_dictionary_entry_t * p_entry;
  530.  
  531.     p_entry = (vlc_dictionary_entry_t *)malloc(sizeof(*p_entry));
  532.     p_entry->psz_key = strdup( psz_key );
  533.     p_entry->p_value = p_value;
  534.     p_entry->p_next = p_dict->p_entries[i_pos];
  535.     p_dict->p_entries[i_pos] = p_entry;
  536.     if( rebuild )
  537.     {
  538.         /* Count how many items there was */
  539.         int count;
  540.         for( count = 1; p_entry->p_next; count++ )
  541.             p_entry = p_entry->p_next;
  542.         if( count > 3 ) /* XXX: this need tuning */
  543.         {
  544.             /* Here it starts to be not good, rebuild a bigger dictionary */
  545.             struct vlc_dictionary_t new_dict;
  546.             int i_new_size = ( (p_dict->i_size+2) * 3) / 2; /* XXX: this need tuning */
  547.             int i;
  548.             vlc_dictionary_init( &new_dict, i_new_size );
  549.             for( i = 0; i < p_dict->i_size; i++ )
  550.             {
  551.                 p_entry = p_dict->p_entries[i];
  552.                 while( p_entry )
  553.                 {
  554.                     __vlc_dictionary_insert( &new_dict, p_entry->psz_key,
  555.                                              p_entry->p_value,
  556.                                              false /* To avoid multiple rebuild loop */);
  557.                     p_entry = p_entry->p_next;
  558.                 }
  559.             }
  560.  
  561.             vlc_dictionary_clear( p_dict, NULL, NULL );
  562.             p_dict->i_size = new_dict.i_size;
  563.             p_dict->p_entries = new_dict.p_entries;
  564.         }
  565.     }
  566. }
  567.  
  568. static inline void
  569. vlc_dictionary_insert( vlc_dictionary_t * p_dict, const char * psz_key, void * p_value )
  570. {
  571.     __vlc_dictionary_insert( p_dict, psz_key, p_value, true );
  572. }
  573.  
  574. static inline void
  575. vlc_dictionary_remove_value_for_key( const vlc_dictionary_t * p_dict, const char * psz_key,
  576.                                      void ( * pf_free )( void * p_data, void * p_obj ),
  577.                                      void * p_obj )
  578. {
  579.     if( !p_dict->p_entries )
  580.         return;
  581.  
  582.     int i_pos = DictHash( psz_key, p_dict->i_size );
  583.     vlc_dictionary_entry_t * p_entry = p_dict->p_entries[i_pos];
  584.     vlc_dictionary_entry_t * p_prev;
  585.  
  586.     if( !p_entry )
  587.         return; /* Not found, nothing to do */
  588.  
  589.     /* Hash collision */
  590.     p_prev = NULL;
  591.     do {
  592.         if( !strcmp( psz_key, p_entry->psz_key ) )
  593.         {
  594.             if( pf_free != NULL )
  595.                 ( * pf_free )( p_entry->p_value, p_obj );
  596.             if( !p_prev )
  597.                 p_dict->p_entries[i_pos] = p_entry->p_next;
  598.             else
  599.                 p_prev->p_next = p_entry->p_next;
  600.             free( p_entry->psz_key );
  601.             free( p_entry );
  602.             return;
  603.         }
  604.         p_prev = p_entry;
  605.         p_entry = p_entry->p_next;
  606.     } while( p_entry );
  607.  
  608.     /* No key was found */
  609. }
  610.  
  611. #endif
  612.